home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / control.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-30  |  29.0 KB  |  1,107 lines

  1. /* This is file CONTROL.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* Merged DPMI and V1.09 C. Sandmann sandmann@clio.rice.edu */
  18.  
  19. #include <dos.h>
  20. #include <dir.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <fcntl.h>
  24. #include <sys/stat.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <io.h>
  28.  
  29. #include "gotypes.h"
  30. #include "gdt.h"
  31. #include "idt.h"
  32. #include "tss.h"
  33. #include "valloc.h"
  34. #include "utils.h"
  35. #include "graphics.h"
  36. #include "mono.h"
  37. #include "vcpi.h"
  38. #include "paging.h"
  39. #include "dpmi.h"
  40. #include "extdebug.h"
  41. #include "exphdlr.h"
  42. #include "dalloc.h"
  43. #include "vcpi.h"
  44. #include "mswitch.h"
  45. #include "xms.h"
  46. #include "npx.h"
  47. #include "stubinfo.h"
  48. #include "proginfo.h"
  49. #include "control.h"
  50. #include "eventque.h"
  51. #include "glob.h"
  52.  
  53. /* stamp.c will find this and replace it with the correct timestamp
  54.    but leave the TIMETIME key alone */
  55. static char build_time[] = "TIMETIMExxx xxx xx xx:xx:xx xxxx";
  56.  
  57. StubInfo stub_info = {
  58.   STUB_INFO_MAGIC,
  59.   sizeof(StubInfo),
  60.   "go32",
  61.   {
  62.     GO32_RELEASE_NUMBER,
  63.     GO32_RELEASE_TYPE_C,
  64.     GO32_MINOR_VERSION,
  65.     GO32_MAJOR_VERSION
  66.   },
  67.   262144L,
  68.   0L,
  69.   "",
  70.   1,
  71.   0L
  72. };
  73.  
  74. PROGINFO prog_info;
  75.  
  76. int topline_info = 0;
  77. int show_memory_info = 0;
  78.  
  79. extern transfer_buffer[];
  80. extern word32 transfer_linear;
  81.  
  82. extern int ctrl_c_flag, in_hardware_interrupt;
  83.  
  84. GDT_S gdt[g_num];
  85. IDT idt[256];
  86.  
  87. TSS *tss_ptr;
  88. int debug_mode = 0;
  89. int self_contained;
  90. long header_offset = 0;
  91. int use_ansi=0;
  92. int use_mono=0;
  93. int redir_1_mono=0;
  94. int redir_2_mono=0;
  95. int redir_2_1=0;
  96. int redir_1_2=0;
  97.  
  98. static FILE *core_log_file = stderr;
  99. static char *corefile = NULL;
  100.  
  101. static int initial_argc;
  102. int old_video_mode;
  103. static int globbing=-1;
  104. static int old_mask1, old_mask2;
  105.  
  106. int16 ems_handle=0;        /*  Get EMS Handle  */
  107. word16 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  108. char use_DPMI = 0;
  109. extern word32 DPMI_STACK;
  110. word32 ARENA = 0x10000000L;
  111.  
  112. int ctrl_break_hit = 0;
  113.  
  114. extern word32 far *pd;
  115.  
  116. extern void far ivec0(void), ivec1(void);
  117. extern void ivec7(void), ivec75(void);
  118. extern void interrupt_common(void), page_fault(void);
  119. extern void v74_handler(void), v78_handler(void), v79_handler(void);
  120.  
  121. void interrupt (*old_ctrlbrk)(void);
  122.  
  123. void set_command_line(char **argv);
  124.  
  125. int exitDPMI = 0;
  126.  
  127. char *exception_names[] = {
  128.   "Division by Zero",
  129.   "Debug",
  130.   0,
  131.   "Breakpoint",
  132.   "Overflow",
  133.   "Bounds Check",
  134.   "Invalid Opcode",
  135.   "Coprocessor not available",
  136.   "Double Fault",
  137.   "Coprocessor overrun",
  138.   "Invalid TSS",
  139.   "Segment Not Present",
  140.   "Stack Fault",
  141.   "General Protection Fault",
  142.   "Page fault",
  143.   0,
  144.   "Coprocessor Error",
  145.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  146.   "Unsupported DOS request"
  147. };
  148. #define EXCEPTION_COUNT (sizeof(exception_names)/sizeof(exception_names[0]))
  149.  
  150. unsigned int cdecl _openfd[255] = {
  151.   0x6001,0x7002,0x6002,0xa004,0xa002,0xffff,0xffff,0xffff,
  152.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  153.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  154.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  155.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  156.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  157.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  158.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  159.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  160.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  161.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  162.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  163.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  164.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  165.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  166.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  167.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  168.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  169.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  170.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  171.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  172.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  173.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  174.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  175.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  176.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  177.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  178.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  179.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  180.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  181.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  182.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  183. };
  184.  
  185. void bump_file_limit(void)
  186. {
  187.   if (((((int)_osmajor)<<8)|_osminor) < 0x0303)
  188.     return;
  189.   _AH = 0x67;
  190.   _BX = 255;
  191.   geninterrupt(0x21);
  192. }
  193.  
  194. void initialize_printer(void)
  195. {
  196.   _BX=4;
  197.   _AH=0x44;
  198.   _AL=0x01;
  199.   _DX=0xa0;
  200.   geninterrupt(0x21);
  201.   setmode(4, O_BINARY);
  202. }
  203.  
  204. void fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  205. {
  206.   GDT_S *g;
  207.   g = gdt+sel;
  208.   if (G & 2)
  209.     limit = limit >> 12;
  210.   g->lim0 = limit & 0xffff;
  211.   g->lim1 = (limit>>16) & 0x0f;
  212.   g->base0 = base & 0xffff;
  213.   g->base1 = (base>>16) & 0xff;
  214.   g->base2 = (base>>24) & 0xff;
  215.   g->stype = type;
  216.   g->lim1 |= G * 0x40;
  217. }
  218.  
  219. void setup_tss(TSS *t, void (*eip)())
  220. {
  221.   memset(t, 0, sizeof(TSS));
  222.   t->tss_cs = g_rcode*8;
  223.   t->tss_eip = (long)FP_OFF(eip);
  224.   t->tss_ss = g_rdata*8;
  225.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  226.   t->tss_ds = g_rdata*8;
  227.   t->tss_es = g_rdata*8;
  228.   t->tss_fs = g_rdata*8;
  229.   t->tss_eflags = 0x0200;
  230.   t->tss_iomap = 0xffff; /* no map */
  231. }
  232.  
  233. void abort(void);
  234.  
  235. void my_abort()
  236. {
  237.   static int recursing = 0;
  238.   if (recursing)
  239.     _exit(1);
  240.   recursing = 1;
  241.   printf("Abort!\n");
  242.   exit(1);
  243. }
  244.  
  245. void exit_func(void)
  246. {
  247.   int i;
  248.   dalloc_uninit();
  249.   EventQueueDeInit();
  250.   uninit_controllers();
  251.   setvect(0x1b, old_ctrlbrk);
  252.   _restorezero();
  253.   if(!use_DPMI) {
  254.     valloc_uninit();
  255.     if ((ems_handle)&&(ems_handle != -1))
  256.       ems_free(ems_handle);    /*  Deallocated EMS Page    */
  257.     if (vcpi_installed)
  258.       vcpi_flush();        /*  Deallocated VCPI Pages  */
  259.   } else {
  260.     DPMIprotectedMode();
  261.     clearDPMIstate();
  262.     restoreDPMIvector();
  263.     uninitDPMI(exitDPMI);
  264.   }
  265.   if (topline_info)
  266.     for (i=0; i<80; i++)
  267.       poke(screen_seg, i*2, 0x0720);
  268.   outportb(0x21, old_mask1);
  269.   outportb(0xa1, old_mask2);
  270. }
  271.  
  272. static void open_core_log(void)
  273. {
  274.   FILE *fp;
  275.  
  276.   if (corefile && ((fp = fopen(corefile, "at")) != NULL))
  277.     {
  278.       core_log_file = fp;
  279.       fprintf(stderr,
  280.           "\nEXCEPTION OCCURRED!  Information dumped to core file:\n");
  281.       fprintf(stderr, "    \"%s\"   \n", corefile);
  282.       fprintf(core_log_file, "\n====================\n");
  283.     }
  284.   else
  285.     {
  286.       corefile = NULL;
  287.       core_log_file = stderr;
  288.     }
  289. }
  290.  
  291. static void close_core_log(void)
  292. {
  293.   if (corefile)
  294.     {
  295.       fclose(core_log_file);
  296.       corefile = NULL;
  297.       core_log_file = stderr;
  298.     }
  299. }
  300.  
  301. void show_call_frame(void)
  302. {
  303.   word32 vbp,vbp_new, tos;
  304.   int max=0;
  305.  
  306.   if (tss_ptr == &ed_tss)
  307.     tos = 0xb0000000L;
  308.   else
  309.     tos = 0x90000000L;
  310.   vbp = tss_ptr->tss_ebp;
  311.   fprintf(core_log_file,
  312.       "Call frame traceback EIPs:\n  0x%08lx\n",tss_ptr->tss_eip);
  313.   if (vbp == 0) return;
  314.   do {
  315.     vbp_new = peek32(vbp+ARENA);
  316.     if (vbp_new == 0) break;
  317.     fprintf(core_log_file,"  0x%08lx\n",peek32(vbp+ARENA+4));  /* EIP */
  318.     vbp = vbp_new;
  319.     if (++max == 10 && corefile)
  320.       break;
  321.   } while ((vbp >=tss_ptr->tss_esp) && (vbp < tos));
  322.   /* 0x9000000 = areas[A_stack].last_addr for DPMI, but stack can be moved */
  323.   
  324.   if (corefile)
  325.   {
  326.     vbp = tss_ptr->tss_esp;
  327.     fprintf(core_log_file, "\nContents of stack:\n");
  328.     for(max=0; max<20; max++)
  329.     {
  330.       fprintf(core_log_file, "  stack[0x%08lx] = 0x%08lx\t", vbp, peek32(vbp+ARENA));
  331.       vbp += 2;
  332.       fprintf(core_log_file, "  stack[0x%08lx] = 0x%08lx\n", vbp, peek32(vbp+ARENA));
  333.       vbp += 2;
  334.     }
  335.   }
  336. }
  337.  
  338. void do_faulting_finish_message(int print_reason, int exit_code)
  339. {
  340.   if (peekb(0x40, 0x49) != old_video_mode)
  341.   {
  342.     _AX = old_video_mode;
  343.     geninterrupt(0x10);
  344.   }
  345.   open_core_log();
  346.   if (tss_ptr->tss_irqn == hard_master_lo+1)
  347.   {
  348.     fprintf(core_log_file, "Ctrl-%s Hit!  Stopped at address %lx\n",
  349.       ctrl_break_hit ? "Break" : "C", tss_ptr->tss_eip);
  350.     if (ctrl_break_hit)
  351.       show_call_frame();
  352.   }
  353.   else
  354.   {
  355.     if (print_reason)
  356.     {
  357.       char *en = (tss_ptr->tss_irqn >= EXCEPTION_COUNT) ? 0 : exception_names[tss_ptr->tss_irqn];
  358.       if (tss_ptr->tss_irqn == hard_slave_lo + 5)
  359.     en = "Floating Point exception";
  360.       if (en == 0)
  361.     fprintf(core_log_file, "Exception %d (0x%02x) at eip=%lx\n",
  362.         tss_ptr->tss_irqn, tss_ptr->tss_irqn, tss_ptr->tss_eip);
  363.       else
  364.     fprintf(core_log_file, "%s at eip=%lx\n", en, tss_ptr->tss_eip);
  365.     }
  366.     fprintf(core_log_file,
  367.         "eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  368.        tss_ptr->tss_eax,
  369.        tss_ptr->tss_ebx,
  370.        tss_ptr->tss_ecx,
  371.        tss_ptr->tss_edx,
  372.        tss_ptr->tss_esi,
  373.        tss_ptr->tss_edi);
  374.     fprintf(core_log_file,
  375.         "ebp=%08lx esp=%08lx cs=%x ds=%x es=%x fs=%x gs=%x ss=%x cr2=%08x\n",
  376.        tss_ptr->tss_ebp,
  377.        tss_ptr->tss_esp,
  378.        tss_ptr->tss_cs,
  379.        tss_ptr->tss_ds,
  380.        tss_ptr->tss_es,
  381.        tss_ptr->tss_fs,
  382.        tss_ptr->tss_gs,
  383.        tss_ptr->tss_ss,
  384.        tss_ptr->tss_cr2);
  385.     show_call_frame();
  386.   }
  387.   close_core_log();
  388.   exit(exit_code);
  389. }
  390.  
  391. int ctrl_c_flag = 0;
  392.  
  393. void interrupt ctrl_break_func(void)
  394. {
  395.   ctrl_break_hit = 1;
  396.   tss_ptr->tss_irqn = hard_master_lo + 1;
  397.   if (!in_hardware_interrupt)
  398.     old_ctrlbrk();
  399. }
  400.  
  401. int ctrlbrk_func(void)
  402. {
  403.   tss_ptr->tss_irqn = hard_master_lo + 1;
  404.   do_faulting_finish_message(1,3);
  405.   return 0;
  406. }
  407.  
  408. char *char2rtype(word8 r, word8 relnum)
  409. {
  410.   static char buf[20];
  411.   char *fmt = "";
  412.   switch (r)
  413.   {
  414.     case 'a': fmt = ".alpha%d"; break;
  415.     case 'b': fmt = ".beta%d"; break;
  416.     case 'f': fmt = ""; break;
  417.     case 'm': fmt = ".maint%d"; break;
  418.     case 's': fmt = ".special%d"; break;
  419.     default : fmt = ".unknown%d"; break;
  420.   }
  421.   sprintf(buf, fmt, relnum);
  422.   return buf;
  423. }
  424.  
  425. void usage(char *s)
  426. {
  427.   word32 lowest_ver = GO32_LOWEST_COMPATIBLE_VERSION;
  428.   word8 *l = (word8 *)(&lowest_ver);
  429.   use_mono = 0;
  430.   fprintf(stderr, "Lowest version I can run is %d.%02d%s\n",
  431.       l[3], l[2], char2rtype(l[1], l[0]));
  432.   if (initial_argc > 1)
  433.     fprintf(stderr, "Invalid go32 usage running %s\n", s);
  434.   fprintf(stderr, "go32.exe usage: go32 [-d {debugger}] [{program} [{options} . . . ]]\n");
  435.   fprintf(stderr, "go32.exe build time was %s\n", build_time+8);
  436.   show_memory_info = 1;
  437.   if (use_DPMI)
  438.   {
  439.     DPMImaxmeminfo inf;
  440.     DPMIprotectedMode();
  441.     DPMImaxmem(&inf);
  442.     DPMIrealMode();
  443.     if (inf.physical_mem == -1 || inf.swap_mem == -1)
  444.       fprintf(stderr, "DPMI virtual memory available: %ld Kb\n", inf.largest_block / 1024L);
  445.     else
  446.     {
  447.       fprintf(stderr, "DPMI memory available: %ld Kb\n", inf.physical_mem * 4L);
  448.       fprintf(stderr, "Swap space available: %ld Kb\n", inf.swap_mem * 4L);
  449.     }
  450.   }
  451.   else
  452.   {
  453.     valloc_init();
  454.     dalloc_init();
  455.   }
  456.   exit(1);
  457. }
  458.  
  459. static void copyright(void)
  460. {
  461.   fprintf(stderr, "go32 version %d.%d%s Copyright (C) 1994 DJ Delorie\n",
  462.       GO32_MAJOR_VERSION,
  463.       GO32_MINOR_VERSION,
  464.       char2rtype(GO32_RELEASE_TYPE_C, GO32_RELEASE_NUMBER));
  465. }
  466.  
  467. int have_80387;
  468. int use_xms=0;
  469. static word32 push32(void *ptr, int len);
  470.  
  471. void setup_idt_task(int which, int tss)
  472. {
  473.   idt[which].selector = tss*8;
  474.   idt[which].stype = 0x8500;
  475.   idt[which].offset0 = 0;
  476.   idt[which].offset1 = 0;
  477. }
  478.  
  479. void init(int argc, char **argv)
  480. {
  481.   int i, n, emu_installed=0;
  482.   struct stat stbuf;
  483.   char *cp, *path, *emu_fn=0;
  484.   unsigned short header[3];
  485.   char *external_debugger = 0;
  486.   char *running_fname;
  487.   DPMIinfo info;
  488.   int disable_dpmi = 0;
  489.   char *argv0_to_pass = argv[0];
  490.   int need_to_free_argv0_to_pass = 0;
  491.   char *argv0_to_run;
  492.   unsigned psp_to_get_args_from = _psp;
  493.   char *tb = (char *)transfer_buffer;
  494.  
  495.   initial_argc = argc;
  496.  
  497.   fprintf(stderr, "");
  498.   fflush(stderr);
  499.   fprintf(stdout, "");
  500.   fflush(stdout);
  501.  
  502.   old_mask1 = inportb(0x21);
  503.   old_mask2 = inportb(0xa1);
  504.  
  505.   /* make calls to abort() really call my_abort() */
  506.   i = _CS;
  507.   n = (int)(abort);
  508.   pokeb(i, n, 0xe9);
  509.   poke(i, n+1, (int)(my_abort) - (n + 3));
  510.  
  511.   cp = getenv("GO32");
  512.   path = 0;
  513.   if (cp)
  514.     while (1)
  515.     {
  516.       char sw[100];
  517.       char val[100];
  518.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  519.     break;
  520.       cp += i;
  521.       if (stricmp(sw, "ansi") == 0)
  522.     use_ansi = 1;
  523.       else if (stricmp(sw, "topline") == 0)
  524.     topline_info = 1;
  525.       else if (stricmp(sw, "meminfo") == 0)
  526.     show_memory_info = 1;
  527.       else if (stricmp(sw, "mono") == 0)
  528.     use_mono = 1;
  529.       else if (stricmp(sw, "2r1") == 0)
  530.     redir_2_1 = 1;
  531.       else if (stricmp(sw, "1r2") == 0)
  532.     redir_1_2 = 1;
  533.       else if (stricmp(sw, "2rm") == 0)
  534.     redir_2_mono = 1;
  535.       else if (stricmp(sw, "1rm") == 0)
  536.     redir_1_mono = 1;
  537.       else if (stricmp(sw, "glob") == 0)
  538.     globbing = 1;
  539.       else if (stricmp(sw, "noglob") == 0)
  540.     globbing = 0;
  541.       else if (stricmp(sw, "nodpmi") == 0)
  542.     disable_dpmi = 1;
  543.       else
  544.       {
  545.     val[0] = 0;
  546.     sscanf(cp, "%s%n", val, &i);
  547.     cp += i;
  548.     if (val[0] == 0)
  549.       break;
  550.       }
  551.       if (stricmp(sw, "driver") == 0)
  552.       {
  553.     if (path) free(path);
  554.     path = strdup(val);
  555.       }
  556.       else if (stricmp(sw, "dpmistack") == 0)
  557.     DPMI_STACK = (atol(val) + 0xfffL) & ~0xfffL;
  558.       else if (stricmp(sw, "tw") == 0)
  559.     gr_def_tw = atoi(val);
  560.       else if (stricmp(sw, "th") == 0)
  561.     gr_def_th = atoi(val);
  562.       else if (stricmp(sw, "gw") == 0)
  563.     gr_def_gw = atoi(val);
  564.       else if (stricmp(sw, "gh") == 0)
  565.     gr_def_gh = atoi(val);
  566.       else if (stricmp(sw, "nc") == 0)
  567.     gr_def_numcolor = atoi(val);
  568.       else if (stricmp(sw, "core") == 0)
  569.       {
  570.     if (corefile)
  571.       free(corefile);
  572.     corefile = strdup(val);
  573.       }
  574.       else if (stricmp(sw, "emu") == 0)
  575.       {
  576.     if (emu_fn) free(emu_fn);
  577.     emu_fn = strdup(val);
  578.       }
  579.     }
  580.  
  581.   if (redir_1_2 && redir_1_2)
  582.   {
  583.     int save_stdout = dup(1);
  584.     dup2(2, 1);
  585.     dup2(save_stdout, 2);
  586.     close(save_stdout);
  587.   }
  588.   else if (redir_2_1)
  589.   {
  590.     dup2(1, 2);
  591.   }
  592.   else if (redir_1_2)
  593.   {
  594.     dup2(2, 1);
  595.   }
  596.  
  597.   if (peekb(0x40,0x49) == 7)
  598.     screen_seg = 0xb000;
  599.   if (!topline_info)
  600.     use_mono = 0;
  601.   if (use_mono)
  602.     screen_seg = 0xb000;
  603.  
  604.   if (!disable_dpmi)
  605.   {
  606.     if (initDPMI(&info))
  607.     {
  608.       hard_master_lo = info.PIC.master;
  609.       hard_slave_lo = info.PIC.slave;
  610.       setDPMIvector();
  611.       DPMIrealMode();
  612.       use_DPMI = 1;
  613.       ARENA = 0;
  614.     }
  615.   }
  616.   if (!use_DPMI)
  617.   {
  618.     if (xms_installed())
  619.       use_xms = 1;
  620.   }
  621.  
  622.   bump_file_limit();
  623.   old_video_mode = peekb(0x40, 0x49);
  624.  
  625.   if (strcmp(argv[1], "!proxy") == 0)
  626.   {
  627.     int a0seg, a0ofs, l;
  628.  
  629.     sscanf(argv[3], "%x", &a0seg);
  630.     sscanf(argv[4], "%x", &a0ofs);
  631.     a0ofs = peek(a0seg, a0ofs);
  632.     for (l=0; peekb(a0seg, a0ofs+l); l++);
  633.     argv0_to_pass = (char *)malloc(l+1);
  634.     for (l=0; (argv0_to_pass[l] = peekb(a0seg, a0ofs+l)) != 0; l++);
  635.     argv0_to_pass[l] = 0;
  636.     need_to_free_argv0_to_pass = 1;
  637.  
  638.     if (argc > 6)
  639.     {
  640.       word32 this_version;
  641.       static word8 tvp[4] = { GO32_RELEASE_NUMBER, GO32_RELEASE_TYPE_C, GO32_MINOR_VERSION, GO32_MAJOR_VERSION };
  642.       int stubinfo_ofs, stubinfo_seg;
  643.       int si_len = sizeof(StubInfo);
  644.       StubInfo far *stubinfo_ptr;
  645.  
  646.       sscanf(argv[5], "%x", &stubinfo_seg);
  647.       sscanf(argv[6], "%x", &stubinfo_ofs);
  648.       stubinfo_ptr = (StubInfo far *)MK_FP(stubinfo_seg, stubinfo_ofs);
  649.       if (si_len > (int)stubinfo_ptr->struct_length)
  650.     si_len = (int)stubinfo_ptr->struct_length;
  651.       movedata(stubinfo_seg, stubinfo_ofs, FP_SEG(&stub_info), FP_OFF(&stub_info), si_len);
  652.  
  653.       if (DPMI_STACK < stub_info.min_stack)
  654.     DPMI_STACK = stub_info.min_stack;
  655.  
  656.       this_version = *(word32 *)tvp;
  657.  
  658.       if (stub_info.required_go32_version[1] == 's')
  659.     if (required_go32_version_w(stub_info) != this_version)
  660.     {
  661.       copyright();
  662.       fprintf(stderr, "Error: Special version (%d.%d.special%d) of go32 required to run this program.\n",
  663.           stub_info.required_go32_version[3],
  664.           stub_info.required_go32_version[2],
  665.           stub_info.required_go32_version[0]);
  666.       exit(1);
  667.     }
  668.       if (required_go32_version_w(stub_info) > this_version)
  669.       {
  670.     copyright();
  671.     fprintf(stderr, "Error: This program requires a version of go32 (%d.%d%s) newer than this one.\n",
  672.         stub_info.required_go32_version[3],
  673.         stub_info.required_go32_version[2],
  674.         char2rtype(stub_info.required_go32_version[1], stub_info.required_go32_version[0]));
  675.     exit(1);
  676.       }
  677.       if (required_go32_version_w(stub_info) < GO32_LOWEST_COMPATIBLE_VERSION)
  678.       {
  679.     copyright();
  680.     fprintf(stderr, "Error: This program requires a version of go32 (%d.%d%s) older than this one.\n",
  681.         stub_info.required_go32_version[3],
  682.         stub_info.required_go32_version[2],
  683.         char2rtype(stub_info.required_go32_version[1], stub_info.required_go32_version[0]));
  684.     exit(1);
  685.       }
  686.       
  687.     }
  688.  
  689.     if (argc > 7)
  690.       sscanf(argv[7], "%x", &psp_to_get_args_from);
  691.   }
  692.  
  693.   if (globbing == -1)
  694.     globbing = stub_info.enable_globbing;
  695.  
  696.   for (i=0; i<128; i++)
  697.     tb[i] = peekb(psp_to_get_args_from, i+128);
  698.   tb[tb[0]+1] = 0;
  699.   __glob_args(tb+1, argv0_to_pass, globbing);
  700.   argc = __glob_argc;
  701.   argv = __glob_argv;
  702.   if (need_to_free_argv0_to_pass)
  703.     free(argv0_to_pass);
  704.  
  705.   if (!use_DPMI)
  706.   {
  707.     ems_handle = emm_present();
  708.     switch (cputype())
  709.     {
  710.     case 1:
  711.       if ((ems_handle)&&(ems_handle != -1))
  712.     ems_free(ems_handle);
  713.       fprintf(stderr, "CPU must be a 386 to run this program.\n");
  714.       exit(1);
  715.     case 2:
  716.       if (ems_handle)
  717.       {
  718.     if ((vcpi_installed = vcpi_present()) != 0)
  719.       break;
  720.     else if (ems_handle != -1)
  721.       ems_free(ems_handle);
  722.       }
  723.       fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program without VCPI.\n");
  724.       fprintf(stderr, "(If you are using an EMS emulator, make sure that EMS isn't disabled)\n");
  725.       exit(1);
  726.     }
  727.   }
  728.  
  729.   _fmode = O_BINARY;
  730.   setup_graphics_driver(path);
  731.   if (path) free(path);
  732.  
  733.   setbuf(stdin, 0);
  734.   atexit((atexit_t)exit_func);
  735.   ctrlbrk(ctrlbrk_func);
  736.   old_ctrlbrk = getvect(0x1b);
  737.   setvect(0x1b, ctrl_break_func);
  738.   n = (int)ivec1-(int)ivec0;
  739.   for (i=0; i<256; i++)
  740.   {
  741.     idt[i].selector = g_altc*8;
  742.     idt[i].stype = 0x8e00;
  743.     idt[i].offset0 = (int)FP_OFF(ivec0) + n*i;
  744.     idt[i].offset1 = 0;
  745.   }
  746.   setup_idt_task(14, g_ptss);
  747.  
  748.   cp = getenv("387");
  749.   if (cp)
  750.     if (tolower(cp[0]) == 'n')
  751.       have_80387 = 0;
  752.     else if (tolower(cp[0]) == 'y')
  753.       have_80387 = 1;
  754.     else
  755.       have_80387 = detect_80387();
  756.   else
  757.     have_80387 = detect_80387();
  758.  
  759.   if (cp && (tolower(cp[0]) == 'q'))
  760.     if (have_80387)
  761.       printf("An 80387 has been detected.\n");
  762.     else
  763.       printf("No 80387 has been detected.\n");
  764.  
  765.   fillgdt(g_zero, 0, 0, 0, 0);
  766.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  767.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  768.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  769.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  770.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  771.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  772.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  773.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 1);
  774.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 1);
  775.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 1);
  776.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 1);
  777.   fillgdt(g_rtss, sizeof(TSS), ptr2linear(&r_tss), 0x89, 1);
  778.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  779.   /* CB change: this is done in "graphics.c" now */
  780.   /* here this selector is initted such that we can set up a dummy paging */
  781.   /* function until the first graphics mode set */
  782.   /* also set up the selector for the BIOS data segment */
  783.   /* OLD:
  784.    *  fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  785.    */
  786.   fillgdt(g_BIOSdata, 0xffff, (word32)0x400, 0x92, 0);
  787.   /* end CB change */
  788.   fillgdt(g_v74, sizeof(TSS), ptr2linear(&v74_tss), 0x89, 1);
  789.   fillgdt(g_v78, sizeof(TSS), ptr2linear(&v78_tss), 0x89, 1);
  790.   fillgdt(g_v79, sizeof(TSS), ptr2linear(&v79_tss), 0x89, 1);
  791.   fillgdt(g_altc, 0xffff, ((word32)FP_SEG(ivec0))*16L, 0x9a, 0);
  792.   fillgdt(g_edcs, 0x0fffffffL, 0xa0000000L, 0x9a, 3);
  793.   fillgdt(g_edds, 0x0fffffffL, 0xa0000000L, 0x92, 3);
  794.  
  795.   setup_tss(&c_tss, go_real_mode);
  796.   setup_tss(&a_tss, go_real_mode);
  797.   setup_tss(&o_tss, go_real_mode);
  798.   setup_tss(&f_tss, go_real_mode);
  799.   setup_tss(&ed_tss, go_real_mode);
  800.   setup_tss(&r_tss, go_real_mode);
  801.   setup_tss(&i_tss, interrupt_common);
  802.   setup_tss(&p_tss, page_fault);
  803.   setup_tss(&v74_tss, v74_handler);
  804.   setup_tss(&v78_tss, v78_handler);
  805.   setup_tss(&v79_tss, v79_handler);
  806.   tss_ptr = &a_tss;
  807.  
  808.   a_tss.tss_edx = ptr2linear(&prog_info);
  809.   prog_info.size_of_this_structure_in_bytes = sizeof(PROGINFO);
  810.   prog_info.pid = 42;
  811.   transfer_linear =
  812.     prog_info.linear_address_of_transfer_buffer = ptr2linear(transfer_buffer) + 0xe0000000L;
  813.   prog_info.size_of_transfer_buffer = 4096L;
  814.   prog_info.linear_address_of_stub_info_structure = ptr2linear(&stub_info) + 0xe0000000L;
  815.   prog_info.linear_address_of_original_psp = (word32)_psp*16L + 0xe0000000L;
  816.   prog_info.run_mode = _GO32_RUN_MODE_UNDEF;
  817.   prog_info.run_mode_info = 0;
  818.  
  819.   core_selector =
  820.     a_tss.tss_gs =
  821.       prog_info.selector_for_linear_memory = (word16)(g_core * 8L);
  822.  
  823.   /*  a_tss.tss_esi = 42; */ /* PID */
  824.   if(use_DPMI)
  825.   {
  826.     a_tss.tss_edi = 0;
  827.     prog_info.run_mode = _GO32_RUN_MODE_DPMI;
  828.     prog_info.run_mode_info = (info.version.major << 8)
  829.       | ((info.version.minor/10) << 4)
  830.     | (info.version.minor%10);
  831.   }
  832.   else
  833.     a_tss.tss_edi = ptr2linear(transfer_buffer) + 0xe0000000L;
  834.  
  835.   argv0_to_pass = argv[0];
  836.   for (i=0; argv0_to_pass[i]; i++)
  837.   {
  838.     if (argv0_to_pass[i] == '\\')
  839.       argv0_to_pass[i] = '/';
  840.     argv0_to_pass[i] = tolower(argv0_to_pass[i]);
  841.   }
  842.  
  843.   if (topline_info)
  844.     for (i=0; i<80; i++)
  845.       poke(screen_seg, i*2, 0x0720);
  846.  
  847.   if (stub_info.actual_file_to_run[0])
  848.   {
  849.     char *cp;
  850.     argv0_to_run = (char *)malloc(strlen(argv0_to_pass) + 13);
  851.     strcpy(argv0_to_run, argv0_to_pass);
  852.     for (cp = argv0_to_run + strlen(argv0_to_run) - 1; cp > argv0_to_run; cp--)
  853.       if (cp[-1] == '/' || cp[-1] == '\\' || cp[-1] == ':')
  854.     break;
  855.     strcpy(cp, stub_info.actual_file_to_run);
  856.     if (access(argv0_to_run, 0))
  857.     {
  858.       strcat(cp, ".exe");
  859.       if (access(argv0_to_run, 0))
  860.     cp[strlen(cp)-4] = 0;    /* remove the .exe */
  861.     }
  862.   }
  863.   else
  864.   {
  865.     argv0_to_run = argv0_to_pass;
  866.   }
  867.  
  868.   if (emu_fn == NULL && !have_80387)
  869.   {
  870.     char *emu_try, *last_slash;
  871.  
  872.     /* If no emu_fn specified, and no 80387 is  present, check for an
  873.      * "emu387" file in the  same directory as the extender.  If we find
  874.      * one, we will use that as the 80387 emulator.  Otherwise,
  875.      * no 80387 emulation.
  876.      */
  877.  
  878.     /* Grab the directory containing the extender and append emu387. */
  879.     last_slash = strrchr (argv0_to_run, '/');
  880.     if (last_slash != NULL)
  881.     {
  882.       int path_len = last_slash - argv0_to_run + 1; /* Length incl. '/' */
  883.       emu_try = (char *) malloc (path_len + 7);
  884.       strncpy (emu_try, argv0_to_run, path_len);
  885.       strcpy (emu_try + path_len, "emu387");
  886.     }
  887.     else
  888.       emu_try = strdup ("emu387");
  889.  
  890.     if (!stat (emu_try, &stbuf))
  891.       emu_fn = emu_try;        /* Found it. */
  892.     else
  893.       free (emu_try);        /* Nope. */
  894.   }
  895.  
  896.  
  897.   self_contained = 0;
  898.   n = open(argv0_to_run, O_RDONLY|O_BINARY);
  899.   header[0] = 0;
  900.   read(n, header, sizeof(header));
  901.   if (header[0] == 0x5a4d)
  902.   {
  903.     word32 stub_offset;
  904.     header_offset = (long)header[2]*512L;
  905.     if (header[1])
  906.       header_offset += (long)header[1] - 512L;
  907.     lseek(n, header_offset - 4, 0);
  908.     read(n, &stub_offset, 4);
  909.     header[0] = 0;
  910.     read(n, header, sizeof(header));
  911.     if (header[0] == 0x010b)
  912.       self_contained = 1;
  913.     if (header[0] == 0x014c)
  914.       self_contained = 1;
  915.   }
  916.   close(n);
  917.  
  918.   if (self_contained)
  919.   {
  920.     paging_set_file(argv0_to_run);
  921.     running_fname = argv0_to_run;
  922.     emu_installed = emu_install(emu_fn);
  923.     set_command_line(argv);
  924.   }
  925.   else
  926.   {
  927.     header_offset = 0;
  928.     for (cp=argv0_to_run; *cp; cp++)
  929.     {
  930.       if (*cp == '.')
  931.     path = cp;
  932.       if (*cp == '/' || *cp == '\\')
  933.     path = 0;
  934.     }
  935.     if (path)
  936.       *path = 0;
  937.     if (stat(argv0_to_run, &stbuf)) /* not found */
  938.     {
  939.       copyright();
  940.       if (strcmp(argv[1], "-d") == 0 && argc > 2)
  941.       {
  942.         debug_mode = 1;
  943.     external_debugger = argv[2];
  944.     argv += 2;
  945.     argc -= 2;
  946.       }
  947.       if (argv[1] == 0)
  948.     usage(argv0_to_pass);
  949.       paging_set_file(argv[1]);
  950.       running_fname = argv[1];
  951.       emu_installed = emu_install(emu_fn);
  952.       set_command_line(argv+1);
  953.     }
  954.     else            /* found */
  955.     {
  956.       paging_set_file(argv0_to_run);
  957.       running_fname = argv0_to_run;
  958.       emu_installed = emu_install(emu_fn);
  959.       set_command_line(argv);
  960.     }
  961.   }
  962.  
  963.   dalloc_init();
  964.   init_controllers();
  965.   if (have_80387)
  966.   {
  967.     idt[7].selector = g_rcode*8;
  968.     idt[7].offset0 = (int)ivec7;
  969.     idt[7].offset1 = 0;
  970.     idt[hard_slave_lo+5].selector = g_rcode*8;
  971.     idt[hard_slave_lo+5].offset0 = (int)ivec75;
  972.     idt[hard_slave_lo+5].offset1 = 0;
  973.   }
  974.  
  975.   setup_idt_task(0x74, g_v74);
  976.   setup_idt_task(hard_master_lo, g_v78);
  977.   setup_idt_task(hard_master_lo+1, g_v79);
  978.  
  979.   if(!use_DPMI)
  980.     a_tss.tss_eax = (g_core*8L)<<16;
  981.   a_tss.tss_eax |= (word32)hard_master_lo | (((word32)hard_slave_lo)<<8);
  982.  
  983.   prog_info.master_interrupt_controller_base = (word8)hard_master_lo;
  984.   prog_info.slave_interrupt_controller_base = (word8)hard_slave_lo;
  985.  
  986.   if (external_debugger)
  987.     load_external_debugger(external_debugger, running_fname, argv0_to_pass);
  988.  
  989.   if (emu_installed)
  990.   {
  991.     push32(&(a_tss.tss_eip), 4);
  992.     a_tss.tss_eip = emu_start_ip();
  993.   }
  994. }
  995.  
  996. void main(int argc, char **argv)
  997. {
  998.   init(argc, argv);
  999.   go_til_stop(0);
  1000.   do_faulting_finish_message(1,1);
  1001. }
  1002.  
  1003. static word32 push32(void *ptr, int len)
  1004. {
  1005.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  1006.   {
  1007.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  1008.     page_in();
  1009.   }
  1010.   a_tss.tss_esp -= len;
  1011.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  1012.   memput(a_tss.tss_esp+ARENA, ptr, len);
  1013.   return a_tss.tss_esp;
  1014. }
  1015.  
  1016. static int num_actual_args;
  1017.  
  1018. static word32 *a;
  1019.  
  1020. void pusharg(char *ar)
  1021. {
  1022.   int s = strlen(ar);
  1023.   if ((ar[0] == '\'') && (ar[s-1] == '\''))
  1024.   {
  1025.     ar[s-1] = '\0';
  1026.     ar++;
  1027.   }
  1028.   a[num_actual_args] = push32(ar, s+1);
  1029.   num_actual_args++;
  1030. }
  1031.  
  1032. void set_command_line(char **argv)
  1033. {
  1034.   char **envv;
  1035.   unsigned envc, envc32;
  1036.   word32 *e, v, argp, envp, *a;
  1037.   int argc;
  1038.  
  1039.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  1040.   page_in();
  1041.  
  1042.   __glob_env(argv[0]);
  1043.   envv = environ;
  1044.   for (envc=0; envv[envc]; envc++);
  1045.   if (envc > 1000)
  1046.   {
  1047.     fprintf(stderr, "Fatal! no memory to copy environment (max 1000, wanted %d)\n", envc);
  1048.     exit(1);
  1049.   }
  1050.   e = (word32 *)transfer_buffer;
  1051.   envc32 = 0;
  1052.   for (envc=0; envv[envc]; envc++)
  1053.   {
  1054.     char *sp, *dp;
  1055.     int state = 0;
  1056.     sp = dp = envv[envc];
  1057.     while (*sp)
  1058.     {
  1059.       switch (state)
  1060.       {
  1061.         case 0: /* waiting for '=' */
  1062.           if (!isspace(*sp))
  1063.             *dp++ = *sp;
  1064.           if (*sp == '=')
  1065.             state = 1;
  1066.           break;
  1067.         case 1: /* got '=' */
  1068.           if (!isspace(*sp))
  1069.           {
  1070.             *dp++ = *sp;
  1071.             state = 2;
  1072.           }
  1073.           break;
  1074.         case 2: /* in value */
  1075.           *dp++ = *sp;
  1076.           break;
  1077.       }
  1078.       sp++;
  1079.     }
  1080.     while (dp > envv[envc] && isspace(dp[-1]))
  1081.       *--dp = 0;
  1082.     if (state != 0) /* else there was no '=', POSIX says we have to have one */
  1083.     {
  1084.       v = push32(envv[envc], strlen(envv[envc])+1);
  1085.       e[envc32++] = v;
  1086.     }
  1087.   }
  1088.   e[envc32++] = 0;
  1089.   envp = push32(e, (envc32)*sizeof(word32));
  1090.  
  1091.   a = (word32 *)transfer_buffer;
  1092.   if (argc > 1000)
  1093.   {
  1094.     fprintf(stderr, "Fatal! no memory to copy arguments (max 1000, wanted %d)\n", argv);
  1095.     exit(1);
  1096.   }
  1097.   for (argc=0; argv[argc]; argc++)
  1098.     a[argc] = push32(argv[argc], strlen(argv[argc])+1);
  1099.   a[argc] = 0;
  1100.   argp = push32(a, (argc+1)*sizeof(word32));
  1101.  
  1102.   push32(&envp, sizeof(word32));
  1103.   push32(&argp, sizeof(word32));
  1104.   v = argc;
  1105.   push32(&v, sizeof(word32));
  1106. }
  1107.